//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using CommunityServer.Components;
using CommunityServer.Galleries.Components;
using CA = ComponentArt.Web.UI;

namespace CommunityServer.Galleries.Controls
{

	public class CategoryTree : GalleryThemedControl
	{

		#region Private Members

		bool pageHasLoaded = false;
		bool showCheckBox = false;
		//bool directNavigation = true;
		//bool showImageCounts = true;

		#endregion

		#region Child Controls

		protected CA.TreeView TreeView1;

		#endregion

		#region Public Properties

		private ArrayList selectedNodes;
		public virtual ArrayList SelectedNodes
		{
			get
			{
				if(pageHasLoaded)
					return GetSelectedNodes();
				else
				{
					return selectedNodes;
				}
			}
			set
			{
				selectedNodes = value;
				if(pageHasLoaded)
					SetSelectedNodes(value);
			}
		}

		[DefaultValue( "" )]
		public virtual string TreeCommand
		{
			get
			{
				Object state = ViewState["TreeCommand"];
				if(state != null)
					return (string)state;
				return "";
			}
			set { ViewState["TreeCommand"] = value; }
		}

		#endregion

		#region Skin

		protected override void AttachChildControls()
		{
			TreeView1 = (CA.TreeView)FindControl( "TreeView1" );
			TreeView1.ShowLines = false;
			TreeView1.LineImagesFolderUrl =string.Concat(this.TemplateSourceDirectory,"/../Images/CATreeView/small_icons/lines");
			TreeView1.ImagesBaseUrl= string.Concat(this.TemplateSourceDirectory,"/../Images/CATreeView/small_icons"); 

		}

		#endregion

		#region Event Overrides

		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);


		}

		protected override void OnLoad(System.EventArgs e)
		{
			base.OnLoad(e);
			if(!Page.IsPostBack)
				DataBind();
			
			pageHasLoaded = true;
		}
		
		public override void DataBind()
		{
			base.DataBind ();
			BindData();
		}

		#endregion

		/// <summary>
		/// Builds the tree
		/// </summary>
		private void BindData()
		{
			if (this.CurrentGallery.CategorizationType != CategorizationType.Album)
			{
				this.Visible = false;
				return;
			}

			ArrayList rawCategories = PostCategories.GetCategories(CurrentGallery.SectionID, false, false, -1);

			PostCategory.SortBy = CurrentGallery.CategorySortBy;
			rawCategories.Sort() ;

			//Search for disabled (orphanded) parent nodes, removing them and moving their children to the root
			ArrayList categories = new ArrayList();
			ArrayList validParents = new ArrayList();
				validParents.Add(0);	
			foreach(PostCategory c in rawCategories)
				validParents.Add(c.CategoryID);

			foreach(PostCategory c in rawCategories)
			{
				if(!validParents.Contains(c.ParentID))
					c.ParentID = 0;
					
				categories.Add(c);
			}
			
			PostCategory root = new PostCategory();
			//root.Name = "\\";
			root.Name = CurrentGallery.Name;
			root.TotalThreads = CurrentGallery.PostCount;
			root.IsEnabled = true;

			categories.Add(root);

			DataTable dt = CADataConverter.ToDataTable(categories,typeof(PostCategory));

			
			/*if(!dt.Columns.Contains("ParentNodeId"))
				dt.Columns.Add("ParentNodeId", typeof(int));*/
			foreach(DataRow dbRow in dt.Rows)
			{
				if(dbRow["CategoryID"].ToString() == "0")
				{
					dbRow["ParentID"] = DBNull.Value;
				}
			}
			

			DataSet ds = new DataSet();
			ds.Tables.Add(dt);
			ds.Relations.Add("NodeRelation", ds.Tables[0].Columns["CategoryID"], ds.Tables[0].Columns["ParentID"]);

			//Loop through categories to find the root
			foreach(DataRow dbRow in ds.Tables[0].Rows)
			{
				if(dbRow.IsNull("ParentID"))
				{   
					//Write out the root node
//					string nodeName = dbRow["Name"].ToString();
//					if(showImageCounts)
//						//nodeName += string.Format(@" <em>({0})</em>", dbRow["TotalThreads"].ToString()); 
//
//					if(directNavigation)
//						nodeName = string.Format(@"<a href=""{0}"" >{1}</a>", GalleryUrls.Instance().ViewGallery(CurrentGallery.ApplicationKey) ,nodeName);

					CA.TreeViewNode newNode = CreateNode(dbRow["CategoryID"].ToString(), dbRow["Name"].ToString(), TreeView1.ParentNodeImageUrl , true, showCheckBox, false);
					
					//note you now control these options throught the skin / template
					newNode.Attributes.Add("ViewCategoryURL", GalleryUrls.Instance().ViewGallery(CurrentGallery.ApplicationKey));
					
					newNode.Attributes.Add("ImageCount", string.Format(@"({0})", dbRow["TotalThreads"].ToString()));
					
					TreeView1.Nodes.Add(newNode);
					
					//Pass the root to the tree builder
					PopulateSubTree(dbRow, newNode);
				}
			}

			TreeView1.ReloadTemplates(); //Added becuase the Tree wouldnt render templates when placed in the right column
		}
		
		/// <summary>
		/// Sets the checkmarks on the selected categories.  This needs to be done after the 
		/// Datasource and nodes have been added to the tree.
		/// </summary>
		/// <param name="postCategories"></param>
		private void SetSelectedNodes(ArrayList postCategories)
		{
			foreach(CA.TreeViewNode root  in TreeView1.Nodes)
			{
				//reset all nodes to unchecked
				root.UnCheckAll();

				ProcessNodeForSelected(root,postCategories);

				if(root.Nodes.Count > 0) //recurse
					ProcessNodeForSelectedChildren(root, postCategories);

			}
		}

		/// <summary>
		/// Recurses through the node tree to all leaf nodes from a root, processing them
		/// to see if they should be selected
		/// </summary>
		/// <param name="node"></param>
		/// <param name="postCategories"></param>
		private void ProcessNodeForSelectedChildren(CA.TreeViewNode node, ArrayList postCategories)
		{
			foreach(CA.TreeViewNode child in node.Nodes)
			{
				ProcessNodeForSelected(child,postCategories);
				if(child.Nodes.Count > 0) //recurse
					ProcessNodeForSelectedChildren(child, postCategories);

			}
		}

		/// <summary>
		/// Examines the current node and sets the checkmark state if selected
		/// </summary>
		/// <param name="node"></param>
		/// <param name="postCategories"></param>
		private void ProcessNodeForSelected(CA.TreeViewNode node, ArrayList postCategories)
		{
			//See if the node is in the list to be checked
			foreach(PostCategory pc in postCategories)
			{
				if(node.ID == pc.CategoryID.ToString())
					node.Checked = true;
			}
		}

		/// <summary>
		/// Retrieves the checked members from the treecontrol
		/// </summary>
		/// <returns></returns>
		private ArrayList GetSelectedNodes()
		{
			ArrayList al = new ArrayList();
			foreach(CA.TreeViewNode n in TreeView1.CheckedNodes)
			{
				PostCategory pc = new PostCategory();
				pc.Name = n.Text;
				pc.SectionID = this.CurrentGallery.SectionID;
				pc.CategoryID = Globals.SafeInt(n.ID, -1) ;
				al.Add(pc);
			}
			return al;
		}

		/// <summary>
		/// Sets the the selected nodes based on a single PostCategory
		/// </summary>
		/// <param name="pc"></param>
		public void SetSingleSelectedNode(PostCategory pc)
		{
			if(pc != null)
			{
				ArrayList al = new ArrayList();
				al.Add(pc);
				this.SelectedNodes = al;
			}
		}

		/// <summary>
		/// Sets the the selected nodes based on a single PostCategory ID
		/// </summary>
		/// <param name="categoryID"></param>
		public void SetSingleSelectedNode(int categoryID, int sectionID)
		{
			if(categoryID <= 0)
				return;

			SetSingleSelectedNode(PostCategories.GetCategory(categoryID, sectionID));
		}

		/// <summary>
		/// Returns the CategoryID of the first node selected (-1 if none)
		/// </summary>
		/// <returns></returns>
		public int GetFirstSelectedNodeID()
		{
			foreach (PostCategory pc in this.SelectedNodes)
				return pc.CategoryID; 

			return -1;
		}

		/// <summary>
		/// Returns a string array of the names of the selected nodes
		/// </summary>
		/// <returns></returns>
		public string[] SelectedNodeNames()
		{
			ArrayList al = new ArrayList();
			foreach (PostCategory pc in this.SelectedNodes)
				al.Add(pc.Name);

			return (string[]) al.ToArray(typeof (string));

		}


		/// <summary>
		/// Enumerates through the children of a specified root node Adding them to the Tree
		/// </summary>
		/// <param name="dbRow"></param>
		/// <param name="node"></param>
		private void PopulateSubTree(DataRow dbRow, CA.TreeViewNode node)
		{
			foreach (DataRow childRow in dbRow.GetChildRows("NodeRelation"))
			{ 
				//We could add a check here to see if the childRow has children to determine
				//if it is a parent node or leaf node for formatting, if we used different images
//				string nodeName = childRow["Name"].ToString();
//				if(showImageCounts)
//					nodeName += string.Format(@" <em>({0})</em>", childRow["TotalThreads"].ToString()); 
//
//				if(directNavigation)
//					nodeName = string.Format(@"<a href=""{0}"" >{1}</a>", GalleryUrls.Instance().ViewCategory(CurrentGallery.ApplicationKey, (int)childRow["CategoryID"])  , nodeName);
//
				CA.TreeViewNode childNode = CreateNode(childRow["CategoryID"].ToString(), childRow["Name"].ToString(), TreeView1.LeafNodeImageUrl , true, showCheckBox, false);
				
				//note you now control these options throught the skin / template
				childNode.Attributes.Add("ViewCategoryURL", GalleryUrls.Instance().ViewCategory(CurrentGallery.ApplicationKey, (int)childRow["CategoryID"]));
					
				childNode.Attributes.Add("ImageCount", string.Format(@"({0})", childRow["TotalThreads"].ToString()));

				node.Nodes.Add(childNode);
				PopulateSubTree(childRow, childNode);
			}
		}

		/// <summary>
		/// Helper to build a node and set the properties
		/// </summary>
		/// <param name="categoryID"></param>
		/// <param name="text"></param>
		/// <param name="imageurl"></param>
		/// <param name="isExpanded"></param>
		/// <param name="hasCheckmark"></param>
		/// <param name="isChecked"></param>
		/// <returns></returns>
		private CA.TreeViewNode CreateNode(string categoryID, string text, string imageurl, bool isExpanded, bool hasCheckmark, bool isChecked)
		{
			CA.TreeViewNode node = new CA.TreeViewNode();
			node.Text = text; 
			node.ImageUrl = imageurl; 
			node.Expanded = isExpanded;
			node.ShowCheckBox = hasCheckmark;
			node.Checked = isChecked;
			node.ID = categoryID;
			node.TemplateId = "ItemTemplate";
			return node;
		}



	}
}
